from tensorflow.examples.tutorials.mnist import input_data
import tensorflow.compat.v1 as tf
import matplotlib.pyplot as plt
import numpy as np
tf.disable_v2_behavior()
# 设置matplotlib的字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题

# 载入MNIST数据集
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# 超参数设置
learning_rate = 1e-2
max_epoch = 20 #周期

# 定义参数
n_samples = 784  # MNIST图像的像素数
n_classes = 10   # MNIST数据集中的类别数

# 定义占位符
x = tf.placeholder(tf.float32, [None, n_samples], name='x-input')
y = tf.placeholder(tf.float32, [None, n_classes], name='y-input')
keep_prob = tf.placeholder(tf.float32)  # Dropout概率

# 逻辑回归模型参数
weights = tf.Variable(tf.zeros([n_samples, n_classes]), name='weights')
biases = tf.Variable(tf.zeros([n_classes]), name='biases')

# 模型的输出
logits = tf.matmul(x, weights) + biases

# 使用softmax函数计算每个类别的预测概率
prediction = tf.nn.softmax(logits)

# 定义损失函数
cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y))

# 定义训练操作
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)

# 定义准确率计算操作
correct_prediction = tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# 初始化变量
init = tf.global_variables_initializer()

# 启动会话
with tf.Session() as sess:
    sess.run(init)

    # 训练模型
    for epoch in range(max_epoch):
        total_batch = int(mnist.train.num_examples / 100)
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(100)
            sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 0.7})

# 启动会话
with tf.Session() as sess:
    sess.run(init)

    # 训练模型
    for epoch in range(max_epoch):
        total_batch = int(mnist.train.num_examples / 100)
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(100)
            sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 0.7})

        # 计算并打印训练和测试的准确率（以百分比形式）
        train_accuracy = sess.run(accuracy, feed_dict={x: mnist.train.images, y: mnist.train.labels, keep_prob: 1.0})
        test_accuracy = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0})
        # 将准确率转换为百分比并打印

# 省略之前的代码...

# 启动会话
with tf.Session() as sess:
    sess.run(init)

    # 初始化准确率列表
    train_accuracies = []
    test_accuracies = []

    # 训练模型并记录准确率，只在每两个周期记录一次
    for epoch in range(0, max_epoch):
        total_batch = int(mnist.train.num_examples / 100)
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(100)
            sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 0.7})

        # 在每个周期结束计算准确率，但只记录偶数周期的准确率
        train_accuracy = sess.run(accuracy, feed_dict={x: mnist.train.images, y: mnist.train.labels, keep_prob: 1.0})
        test_accuracy = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0})
        if epoch % 2 == 0:
            train_accuracies.append(train_accuracy)
            test_accuracies.append(test_accuracy)
        print("Epoch {0}, 训练准确率 {1:.2f}%, 测试准确率 {2:.2f}%".format(epoch + 1, train_accuracy * 100, test_accuracy * 100))

    # 计算最终的准确率
    final_train_accuracy = sess.run(accuracy, feed_dict={x: mnist.train.images, y: mnist.train.labels, keep_prob: 1.0})
    final_test_accuracy = sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels, keep_prob: 1.0})

    # 打印最终的准确率
    print("\n最终训练准确率: {:.2f}%".format(final_train_accuracy * 100))
    print("最终测试准确率: {:.2f}%".format(final_test_accuracy * 100))

    # 可视化准确率，这里只可视化记录的准确率
    plt.figure(figsize=(12, 6))
    # 生成x轴的偶数步长数据
    x_axis_steps_of_two = list(range(2, max_epoch + 1, 2))
    plt.plot(x_axis_steps_of_two, train_accuracies, label='训练准确率', marker='o')
    plt.plot(x_axis_steps_of_two, test_accuracies, label='测试准确率', marker='o')
    plt.xlabel('训练周期')
    plt.ylabel('准确率')
    plt.title('周期对应的训练和测试准确率')
    plt.legend()
    plt.xticks(x_axis_steps_of_two)
    plt.show()

    # 启动会话
    with tf.Session() as sess:
        sess.run(init)

        # 训练模型
        for epoch in range(max_epoch):
            total_batch = int(mnist.train.num_examples / 100)
            for i in range(total_batch):
                batch_xs, batch_ys = mnist.train.next_batch(100)
                sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 0.7})

        # 随机选取5张图片进行预测
        random_indices = np.random.choice(mnist.test.images.shape[0], 5)  # 随机选择5个索引
        random_digit_images = mnist.test.images[random_indices]  # 选择5张图片
        random_digit_labels = mnist.test.labels[random_indices]  # 选择对应的标签

        # 预测这5张图片的标签
        predictions = sess.run(prediction, feed_dict={x: random_digit_images, keep_prob: 1.0})

        # 打印预测结果
        for i, prediction in enumerate(predictions):
            predicted_label = np.argmax(prediction)
            true_label = np.argmax(random_digit_labels[i])
            print("图片 {0} 的预测标签为 {1}, 真实标签为 {2}".format(i + 1, predicted_label, true_label))

        # 可视化这3张图片
        plt.figure(figsize=(12, 4))
        for i, image in enumerate(random_digit_images):
            plt.subplot(1, 5, i + 1)
            plt.imshow(image.reshape(28, 28), cmap='gray')
            plt.title('预测: {0}, 真实: {1}'.format(np.argmax(predictions[i]), np.argmax(random_digit_labels[i])))
            plt.xticks([])
            plt.yticks([])
        plt.show()